﻿using System;
using Fine.Collections.Const;
using Fine.Collections.Cont;
using JetBrains.Annotations;



namespace Crocodile.LangUtils
{

    /// <summary>
    /// Функции помогающие работать с Reflection.
    /// </summary>
    public static class ReflectionExt
    {

        /// <summary>
        /// Проверяет, является ли указанный тип разновидностью заданного базового типа.
        /// </summary>
        /// <param name="type">проверяемый тип.</param>
        /// <typeparam name="BT">базовый тип.</typeparam>
        /// <returns>true если является.</returns>
        public static bool IsKindOf<BT>(this Type type)
        {
            return typeof(BT).IsAssignableFrom(type);
        }



        /// <summary>
        /// Возвращает список всех properties and fields of the specified type (class or struct),
        /// that meet the given condition.
        /// </summary>
        /// <param name="type">the class or struct which pproperties and fields are asked.</param>
        /// <param name="predicate">the condition (or null if to return all).</param>
        /// <returns>simple data members.</returns>
        public static ConstList<DataMemberInfo> GetSimpleDataMembers(
                            [NotNull] this Type type, 
                            [CanBeNull] Predicate<DataMemberInfo> predicate = null)
        {
            var members = new ArrList<DataMemberInfo>(1);

            foreach (var p in type.GetProperties())
            {
                DataMemberInfo dmi = new PropertyMemeberInfo(p);
                if (predicate == null || predicate(dmi))
                    members.Add(dmi);
            }

            foreach (var f in type.GetFields())
            {
                DataMemberInfo dmi = new FieldMemeberInfo(f);
                if (predicate == null || predicate(dmi))
                    members.Add(dmi);
            }

            return members.TurnIntoConst();
        }
    }
}
